﻿using PMS.Core.Configuration.CommonEnumConfigs;
using PMS.Core.Utils;
using PMS.Data.Entities.Customers;
using System;
using System.Collections.Generic;

namespace PMS.Services.EntityServices.Customers
{
    /// <summary>
    /// Customer service interface
    /// </summary>
    public partial interface ICustomerService
    {
        #region Customers

        /// <summary>
        /// Gets all customers
        /// </summary>
        /// <param name="createdFromUtc">Created date from (UTC); null to load all records</param>
        /// <param name="createdToUtc">Created date to (UTC); null to load all records</param>
        /// <param name="customerRoleIds">A list of customer role identifiers to filter by (at least one match); pass null or empty list in order to load all customers; </param>
        /// <param name="email">Email; null to load all customers</param>
        /// <param name="loginname">Loginname; null to load all customers</param>
        /// <param name="mobile">PhoneNumber; null to load all customers</param>
        /// <param name="nickname">User NickName/Displayname; null to load all customers</param>
        /// <param name="dayOfBirth">Day of birth; 0 to load all customers</param>
        /// <param name="monthOfBirth">Month of birth; 0 to load all customers</param>
        /// <param name="pageIndex">Page index</param>
        /// <param name="pageSize">Page size</param>
        /// <param name="getOnlyTotalCount">A value in indicating whether you want to load only total number of records. Set to "true" if you don't want to load data from database</param>
        /// <returns>Customers</returns>
        IPagedList<Customer> GetAllCustomers(DateTime? createdFromUtc = null, DateTime? createdToUtc = null,
            int[] customerRoleIds = null, string email = null, string loginname = null, string mobile = null, 
            string nickname = null, int dayOfBirth = 0, int monthOfBirth = 0,
            int pageIndex = 0, int pageSize = int.MaxValue, bool getOnlyTotalCount = false);

        /// <summary>
        /// Gets online customers
        /// </summary>
        /// <param name="lastActivityFromUtc">Customer last activity date (from)</param>
        /// <param name="customerRoleIds">A list of customer role identifiers to filter by (at least one match); pass null or empty list in order to load all customers; </param>
        /// <param name="pageIndex">Page index</param>
        /// <param name="pageSize">Page size</param>
        /// <returns>Customers</returns>
        IPagedList<Customer> GetOnlineCustomers(DateTime lastActivityFromUtc,
            int[] customerRoleIds, int pageIndex = 0, int pageSize = int.MaxValue);

        /// <summary>
        /// Gets customers with shopping carts
        /// </summary>
        /// <param name="shoppingCartType">Shopping cart type; pass null to load all records</param>
        /// <param name="storeId">Store identifier; pass 0 to load all records</param>
        /// <param name="productId">Product identifier; pass null to load all records</param>
        /// <param name="createdFromUtc">Created date from (UTC); pass null to load all records</param>
        /// <param name="createdToUtc">Created date to (UTC); pass null to load all records</param>
        /// <param name="countryId">Billing country identifier; pass null to load all records</param>
        /// <param name="pageIndex">Page index</param>
        /// <param name="pageSize">Page size</param>
        /// <returns>Customers</returns>
        //IPagedList<Customer> GetCustomersWithShoppingCarts(ShoppingCartType? shoppingCartType = null,
        //    int storeId = 0, int? productId = null,
        //    DateTime? createdFromUtc = null, DateTime? createdToUtc = null, int? countryId = null,
        //    int pageIndex = 0, int pageSize = int.MaxValue);

        /// <summary>
        /// Gets customer for shopping cart
        /// </summary>
        /// <param name="shoppingCart">Shopping cart</param>
        /// <returns>Result</returns>
        //Customer GetShoppingCartCustomer(IList<ShoppingCartItem> shoppingCart);

        /// <summary>
        /// Gets a value indicating whether customer is registered
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="onlyActiveCustomerRoles">A value indicating whether we should look only in active customer roles</param>
        /// <returns>Result</returns>
        bool IsRegistered(Customer customer, bool onlyActiveCustomerRoles = true);
        /// <summary>
        /// Delete a customer
        /// </summary>
        /// <param name="customer">Customer</param>
        void DeleteCustomer(Customer customer);

        /// <summary>
        /// Gets built-in system record used for background tasks
        /// </summary>
        /// <returns>A customer object</returns>
        Customer GetOrCreateBackgroundTaskUser();

        /// <summary>
        /// Gets a customer
        /// </summary>
        /// <param name="customerId">Customer identifier</param>
        /// <returns>A customer</returns>
        Customer GetCustomerById(int customerId);

        /// <summary>
        /// Get customers by identifiers
        /// </summary>
        /// <param name="customerIds">Customer identifiers</param>
        /// <returns>Customers</returns>
        IList<Customer> GetCustomersByIds(int[] customerIds);

        /// <summary>
        /// Gets a customer by GUID
        /// </summary>
        /// <param name="customerGuid">Customer GUID</param>
        /// <returns>A customer</returns>
        Customer GetCustomerByGuid(Guid customerGuid);

        /// <summary>
        /// Get customer by email
        /// </summary>
        /// <param name="email">Email</param>
        /// <returns>Customer</returns>
        Customer GetCustomerByEmail(string email);

        /// <summary>
        /// Get customer by username(LoginName)
        /// </summary>
        /// <param name="username">Username</param>
        /// <returns>Customer</returns>
        Customer GetCustomerByUsername(string username);

        /// <summary>
        /// Get customer by username(LoginName)
        /// </summary>
        /// <param name="username">Username</param>
        /// <returns>Customer</returns>
        Customer GetCustomerByMobile(string phonenumber);

        /// <summary>
        /// Insert a customer
        /// </summary>
        /// <param name="customer">Customer</param>
        void InsertCustomer(Customer customer);

        /// <summary>
        /// Updates the customer
        /// </summary>
        /// <param name="customer">Customer</param>
        void UpdateCustomer(Customer customer);

        #endregion

        #region Customer roles

        /// <summary>
        /// Add a customer-customer role mapping
        /// </summary>
        /// <param name="roleMapping">Customer-customer role mapping</param>
        void AddCustomerRoleMapping(CustomerCustomerRoleMapping roleMapping);

        /// <summary>
        /// Remove a customer-customer role mapping
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="role">Customer role</param>
        void RemoveCustomerRoleMapping(Customer customer, CustomerRole role);

        /// <summary>
        /// Delete a customer role
        /// </summary>
        /// <param name="customerRole">Customer role</param>
        void DeleteCustomerRole(CustomerRole customerRole);

        /// <summary>
        /// Gets a customer role
        /// </summary>
        /// <param name="customerRoleId">Customer role identifier</param>
        /// <returns>Customer role</returns>
        CustomerRole GetCustomerRoleById(int customerRoleId);

        /// <summary>
        /// Get customer role identifiers
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="showHidden">A value indicating whether to load hidden records</param>
        /// <returns>Customer role identifiers</returns>
        int[] GetCustomerRoleIds(Customer customer, bool showHidden = false);

        /// <summary>
        /// Gets list of customer roles
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="showHidden">A value indicating whether to load hidden records</param>
        /// <returns>Result</returns>
        IList<CustomerRole> GetCustomerRoles(Customer customer, bool showHidden = false);

        /// <summary>
        /// Gets all customer roles
        /// </summary>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <returns>Customer roles</returns>
        IList<CustomerRole> GetAllCustomerRoles(bool showHidden = false);

        /// <summary>
        /// Gets a customer role By roletype
        /// </summary>
        /// <param name="roleType">Customer RoleType</param>
        /// <returns>Customer role</returns>
        CustomerRole GetCustomerRoleByRoleType(RoleType roleType);

        /// <summary>
        /// Inserts a customer role
        /// </summary>
        /// <param name="customerRole">Customer role</param>
        void InsertCustomerRole(CustomerRole customerRole);

        /// <summary>
        /// Gets a value indicating whether customer is in a certain customer role
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="roleType">Customer role type</param>
        /// <param name="onlyActiveCustomerRoles">A value indicating whether we should look only in active customer roles</param>
        /// <returns>Result</returns>
        bool IsInCustomerRole(Customer customer, RoleType roleType, bool onlyActiveCustomerRoles = true);

        /// <summary>
        /// Gets a value indicating whether customer is administrator
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="onlyActiveCustomerRoles">A value indicating whether we should look only in active customer roles</param>
        /// <returns>Result</returns>
        bool IsAdmin(Customer customer, bool onlyActiveCustomerRoles = true);

        /// <summary>
        /// Gets a value indicating whether customer is BuildIn Backend Task User for Schedule Task 
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <returns>Result</returns>
        bool IsBuildInTaskUser(Customer customer);

        /// <summary>
        /// Gets a value indicating whether customer is guest
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="onlyActiveCustomerRoles">A value indicating whether we should look only in active customer roles</param>
        /// <returns>Result</returns>
        bool IsGuest(Customer customer, bool onlyActiveCustomerRoles = true);

        /// <summary>
        /// Updates the customer role
        /// </summary>
        /// <param name="customerRole">Customer role</param>
        void UpdateCustomerRole(CustomerRole customerRole);

        #endregion

        #region Customer passwords

        /// <summary>
        /// Get current customer password
        /// </summary>
        /// <param name="customerId">Customer identifier</param>
        /// <returns>Customer password</returns>
        CustomerPassword GetCurrentPassword(int customerId);

        /// <summary>
        /// Insert a customer password
        /// </summary>
        /// <param name="customerPassword">Customer password</param>
        void InsertCustomerPassword(CustomerPassword customerPassword);

        /// <summary>
        /// Update a customer password
        /// </summary>
        /// <param name="customerPassword">Customer password</param>
        void UpdateCustomerPassword(CustomerPassword customerPassword);

        /// <summary>
        /// Check whether password recovery token is valid
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="token">Token to validate</param>
        /// <returns>Result</returns>
        bool IsPasswordRecoveryTokenValid(Customer customer, string token);

        /// <summary>
        /// Check whether password recovery link is expired
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <returns>Result</returns>
        bool IsPasswordRecoveryLinkExpired(Customer customer);

        /// <summary>
        /// Check whether customer password is expired 
        /// DavidLee 更改检查密码过期检查机制，判断密码过期时效，返回密码过期天数。
        /// 在容错期时间段内，只提醒用户更改密码，在容错期后强制要求用户更改密码
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <returns>expired days if password is expired; otherwise 0</returns>
        int PasswordIsExpired(Customer customer);

        #endregion

        //#region Customer address mapping

        ///// <summary>
        ///// Gets a list of addresses mapped to customer
        ///// </summary>
        ///// <param name="customerId">Customer identifier</param>
        ///// <returns></returns>
        //IList<Address> GetAddressesByCustomerId(int customerId);

        ///// <summary>
        ///// Gets a address mapped to customer
        ///// </summary>
        ///// <param name="customerId">Customer identifier</param>
        ///// <param name="addressId">Address identifier</param>
        ///// <returns>Result</returns>
        //Address GetCustomerAddress(int customerId, int addressId);

        ///// <summary>
        ///// Gets a customer billing address
        ///// </summary>
        ///// <param name="customer">Customer identifier</param>
        ///// <returns>Result</returns>
        //Address GetCustomerBillingAddress(Customer customer);

        ///// <summary>
        ///// Gets a customer shipping address
        ///// </summary>
        ///// <param name="customer">Customer</param>
        ///// <returns>Result</returns>
        //Address GetCustomerShippingAddress(Customer customer);

        ///// <summary>
        ///// Remove a customer-address mapping record
        ///// </summary>
        ///// <param name="customer">Customer</param>
        ///// <param name="address">Address</param>
        //void RemoveCustomerAddress(Customer customer, Address address);

        ///// <summary>
        ///// Inserts a customer-address mapping record
        ///// </summary>
        ///// <param name="customer">Customer</param>
        ///// <param name="address">Address</param>
        //void InsertCustomerAddress(Customer customer, Address address);

        //#endregion
        #region Organize
        /// <summary>
        /// Get All Organize List
        /// </summary>
        /// <returns></returns>
        IList<Organize> GetAllOrganizes();
        #endregion
    }
}
